package com.practice.designMode.builder;


import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class SQL {

    public static SQLBuilder build(SqlType type){
        return new SQLBuilder(type);
    }

    public static SelectBuilder select(){
        return new SelectBuilder();
    }

    public static TableStage update(){
        return new UpdateBuilder();
    }

    /**
     * 第二版，策略模式进行优化
     * 四种类型的sql语句支持的语法实际上是有差异的
     * 例如update 和 select就完全不同，逻辑封装在一起，代码臃肿，难以维护
     * 而且没有对调用进行限制，容易出错，不合法。
     * 使用策略模式进行拆分。
     */
    public static class SelectBuilder{
        private String[] columns;

        private String table;

        private String where;

        public SelectBuilder columns(String... columns){
            this.columns = columns;
            return this;
        }

        public SelectBuilder table(String table){
            this.table = table;
            return this;
        }

        public SelectBuilder where(String where){
            this.where = where;
            return this;
        }

        public String build(){
            StringBuilder sql = new StringBuilder();
            sql.append("SELECT ").append(String.join(",",columns)).append(" FROM ").append(table);
            if(where != null){
                sql.append(" WHERE ").append(where);
            }
            return sql.toString();
        }
    }

    /**
     * 第三版优化——状态机
     * 在sql的编写中，应该需要符合一定的先后语法顺序，因此方法的调用需要按照一定顺序进行控制
     * 使用接口，按照状态机的逻辑，进行调控
     */

    interface TableStage{
        WhereStage table(String table);
    }

    interface WhereStage{
        SetStage where(String where);
    }

    interface SetStage{
        String build();

        SetStage set(String col,String value);
    }

    public static class UpdateBuilder implements TableStage,WhereStage,SetStage{
        private String table;

        private String where;

        private final Map<String,String> setMap = new LinkedHashMap<>();


        public WhereStage table(String table){
            this.table = table;
            return this;
        }

        public SetStage where(String where){
            this.where = where;
            return this;
        }

        public SetStage set(String col,String value){
            this.setMap.put(col,value);
            return this;
        }

        public String build(){
            StringBuilder sql = new StringBuilder();
            sql.append("UPDATE ").append(table).append(" set ");
            String collect = setMap.entrySet().stream().map(entry -> {
                return entry.getKey() + "=" + entry.getValue();
            }).collect(Collectors.joining(","));
            sql.append(collect);
            if(where != null){
                sql.append(" WHERE ").append(where);
            }
            return sql.toString();
        }
    }

    /**
     * 第一版——简单构造器的实现
     */
    public static class SQLBuilder{

        private final SqlType type;

        private String[] columns;

        private String table;

        private String where;

        private final Map<String,String> setMap = new LinkedHashMap<>();

        private SQLBuilder(SqlType type){
            this.type = type;
        }

        public SQLBuilder columns(String... columns){
            this.columns = columns;
            return this;
        }

        public SQLBuilder table(String table){
            this.table = table;
            return this;
        }

        public SQLBuilder where(String where){
            this.where = where;
            return this;
        }

        public SQLBuilder set(String col,String value){
            this.setMap.put(col,value);
            return this;
        }

        public String buildSql(){
            StringBuilder sql = new StringBuilder();
            switch (type){
                case DELETE -> {

                }
                case INSERT -> {

                }
                case SELECT -> {
                    sql.append("SELECT ").append(String.join(",",columns)).append(" FROM ").append(table);
                    if(where != null){
                        sql.append(" WHERE ").append(where);
                    }
                }
                case UPDATE -> {
                    sql.append("UPDATE ").append(" FROM ").append(table);
                    String collect = setMap.entrySet().stream().map(entry -> {
                        return entry.getKey() + "=" + entry.getValue();
                    }).collect(Collectors.joining(","));
                    sql.append(collect);
                    if(where != null){
                        sql.append(" WHERE ").append(where);
                    }

                }
                default -> throw new UnsupportedOperationException("Temp do not support");
            }
            return sql.toString();
        }
    }

    enum SqlType {
        INSERT,
        SELECT,
        DELETE,
        UPDATE,
    }
}
